﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace AIC_Notification
{
    class StatisticsHelper
    {
        private void AggregrateStatistics(IList<SOF_Application> Applications, ref AggregatedStatistics Stats)
        {
            int TotalSchoolInRally = 0;

            Stats.TotalStudents = Applications.Count;

            foreach (var Application in Applications)
            {
                TotalSchoolInRally += Application.ApplicationStats.SchoolInCurrentRally;
                Stats.TotalAssignedDraft += Application.ApplicationStats.TotalAssignedDraft;
                Stats.TotalOverDuedDraft += Application.ApplicationStats.TotalOverDuedDraft;
                Stats.TotalPendingRevision += Application.ApplicationStats.TotalPendingRevision;
                Stats.TotalOverDuedRevision += Application.ApplicationStats.TotalOverDuedRevision;
                Stats.ProgressScore += Application.ApplicationStats.ProgressScore;
                Stats.ProgressScore /= Stats.TotalStudents;
            }

            Stats.AverageSchoolInRally += (double)TotalSchoolInRally / (double)Stats.TotalStudents;
        }

        public void CalculteStatistics()
        {
            // Calculate statistics for each Application
            foreach (var Application in Global.SOF_Applications.Values)
            {
                Global.ProcessingApplication = Application;
                Application.CalculateStatistics();
            }

            // Calculate Teacher Statistics
            foreach (var Teacher in TeacherDB.Teachers)
                AggregrateStatistics(Teacher.Students, ref Teacher.ApplicationStats);          

            // Calculate City Statistics
            foreach (var City in CityDB.Cities)
                AggregrateStatistics(City.Students, ref City.ApplicationStats);

            // Calculate Company Statistics
            AggregrateStatistics(Global.SOF_Applications.Values.ToList<SOF_Application>(), ref Statistics.ApplicationStats);

            // Save in CSV
            Statistics.SaveStatisticsAsCSV();
        }

        private void AddOneApplicationSchoolStatistics(SOF_WorkList School, ref RallySchoolStatistics Stats)
        {
            // Calculate Essay Draft Statistics
            if (School.SchoolStats.NumberOfEssay > 0)
            {
                for (int i = 1; i <= School.SchoolStats.NumberOfEssay; i++)
                {
                    EssayStatistics EStats = School.SchoolStats.EssayStatisticsList.SingleOrDefault(EssayStatistics => EssayStatistics.EssayNumber == i);
                    if (EStats != null)
                    {
                        if (EStats.LatestDraft > Stats.EssayStatistics[i - 1].GetMaxDraft())
                            Stats.EssayStatistics[i - 1].SetMaxDraft(EStats.LatestDraft);
                        if ((Stats.EssayStatistics[i - 1].GetMinDraft() == 0) || (Stats.EssayStatistics[i - 1].GetMinDraft() > EStats.LatestDraft)) // if 0, set to draft; otherwise normal compare.
                            Stats.EssayStatistics[i - 1].SetMinDraft(EStats.LatestDraft);
                        Stats.EssayStatistics[i - 1].SumAverage(EStats.LatestDraft);
                    }
                }
            }
        }

        private int MaxNumberOfEssay(IList<SOF_Application> Applications, int Rally, int SchoolNumber)
        {
            int MaxEssay = 0;
            foreach (var Application in Applications)
            {
                SOF_WorkList School = Application.GetSchool(Rally, SchoolNumber);

                if ((School != null) && (School.SchoolStats.NumberOfEssay > MaxEssay))
                    MaxEssay = School.SchoolStats.NumberOfEssay;
            }

            return MaxEssay;
        }

        private int MaxNumberOfEssay(IList<SOF_Application> Applications, string Name)
        {
            int MaxEssay = 0;
            foreach (var Application in Applications)
            {
                SOF_WorkList School = Application.GetSchool(Name);

                if ((School != null) && (School.SchoolStats.NumberOfEssay > MaxEssay))
                    MaxEssay = School.SchoolStats.NumberOfEssay;
            }

            return MaxEssay;
        }

        public void SetRallyStatus(int Status, ref RallySchoolStatistics Statistics)
        {
            if (Status == 3)
                Statistics.StatusRed += 1;
            else if (Status == 2)
                Statistics.StatusYellow += 1;
            else if (Status == 1)
                Statistics.StatusGreen += 1;
            else if (Status == 4)
                Statistics.StatusYellow += 1;
            else if (Status == -1)
                Statistics.StatusRed += 1;
        }

        public void CalculateEssayStatistics(IList<SOF_Application> Applications, IList<RallySchoolStatistics> RallySchoolStatsList, RallyOfRallySchoolStatistics RallyOfRallySchoolStats)
        {
            int MaxEssayList = 0;
            foreach (var Application in Applications)
            {
                if (Application.NoOfEssayList > MaxEssayList)
                    MaxEssayList = Application.NoOfEssayList;
            }

            int MaxCEFEssay = MaxNumberOfEssay(Applications, "CEF");
            int MaxPSEssay = MaxNumberOfEssay(Applications, "PS");
            int MaxHALEssay = MaxNumberOfEssay(Applications, "HAL");

            // Create Statistics Objects
            RallySchoolStatistics CEF_Stats = new RallySchoolStatistics("CEF", MaxCEFEssay, 0);
            RallySchoolStatistics PS_Stats = new RallySchoolStatistics("PS", MaxPSEssay, 1);
            RallySchoolStatistics HAL_Stats = new RallySchoolStatistics("HAL", MaxHALEssay, 1);

            RallyOfRallySchoolStats.Add(CEF_Stats, 0, 0);
            RallyOfRallySchoolStats.Add(PS_Stats, 1, 0);
            RallyOfRallySchoolStats.Add(HAL_Stats, 1, 1);

            for (int i = 2; i <= RallyHelper.NoOfRally; i++)
            {
                int NoOfSchools = i != RallyHelper.NoOfRally ? 2 : SOF_Application.MAX_SCHOOL_IN_RALLY;
                for (int j = 0; j < NoOfSchools; j++)
                {
                    RallySchoolStatistics TempRaRallySchoolStatistics = new RallySchoolStatistics("School", MaxNumberOfEssay(Applications, i, j), i);
                    RallyOfRallySchoolStats.Add(TempRaRallySchoolStatistics, i, j);
                }
            }

            RallySchoolStatsList.Add(CEF_Stats);
            RallySchoolStatsList.Add(PS_Stats);
            RallySchoolStatsList.Add(HAL_Stats);

            // Calculate Statistics
            foreach (var Application in Applications)
            {
                SOF_WorkList School = null;

                School = Application.GetSchool("CEF");
                if (School != null)
                {
                    CEF_Stats.Total += 1;

                    // Calculate Completion Rate
                    if (School.SchoolStats.NumberOfEssay == 0)
                        CEF_Stats.NotStarted += 1;
                    else if (School.SchoolStats.NumberOfEssay == 1)
                        CEF_Stats.InProgress += 1;
                    else if (School.SchoolStats.NumberOfEssay == 2)
                        CEF_Stats.Completed += 1;

                    // Calculate Essay Draft Statistics
                    AddOneApplicationSchoolStatistics(School, ref CEF_Stats);
                }

                School = Application.GetSchool("PS");
                if (School != null)
                {
                    PS_Stats.Total += 1;

                    // Calculate Completion Rate
                    if (School.SchoolStats.NumberOfEssay == 0)
                        PS_Stats.NotStarted += 1;
                    else if (School.SchoolStats.NumberOfEssay > 0)
                    {
                        if (School.SchoolStats.AllEssayGoalMet)
                            PS_Stats.Completed += 1;
                        else
                            PS_Stats.InProgress += 1;
                    }

                    SetRallyStatus(School.SchoolStats.RallyStatus, ref PS_Stats);

                    AddOneApplicationSchoolStatistics(School, ref PS_Stats);
                }

                School = Application.GetSchool("HAL");
                if (School != null)
                {
                    HAL_Stats.Total += 1;

                    // Calculate Completion Rate
                    if (School.SchoolStats.NumberOfEssay == 0)
                        HAL_Stats.NotStarted += 1;
                    else if (School.SchoolStats.NumberOfEssay > 0)
                    {
                        EssayStatistics HALEssay = School.SchoolStats.EssayStatisticsList.SingleOrDefault(EssayStatistics => EssayStatistics.EssayNumber == 2); // Final HAL (not MAJ)
                        if ((HALEssay != null) && (HALEssay.MetRallyGoal || HALEssay.IsFinal)) // If real HAL is there and is final, then complete.
                            HAL_Stats.Completed += 1;
                        else
                            HAL_Stats.InProgress += 1;
                    }

                    SetRallyStatus(School.SchoolStats.RallyStatus, ref HAL_Stats);

                    AddOneApplicationSchoolStatistics(School, ref HAL_Stats);
                }

                // Essay Stats for Schools
                for (int i = 2; i <= RallyHelper.NoOfRally; i++)
                {
                    int NoOfSchools = i != RallyHelper.NoOfRally ? 2 : SOF_Application.MAX_SCHOOL_IN_RALLY;
                    for (int j = 0; j < NoOfSchools; j++)
                    {
                        SOF_WorkList ApplyingSchool = Application.GetSchool(i, j);

                        if (ApplyingSchool != null)
                        {
                            RallySchoolStatistics TempRaRallySchoolStatistics = RallyOfRallySchoolStats.Get(i, j);

                            TempRaRallySchoolStatistics.Total += 1;

                            // Calculate Completion Rate
                            if (ApplyingSchool.SchoolStats.NumberOfEssay == 0)
                                TempRaRallySchoolStatistics.NotStarted += 1;
                            else if (ApplyingSchool.SchoolStats.NumberOfEssay > 0)
                            {
                                if (ApplyingSchool.SchoolStats.AllEssayGoalMet)
                                    TempRaRallySchoolStatistics.Completed += 1;
                                else
                                    TempRaRallySchoolStatistics.InProgress += 1;
                            }

                            SetRallyStatus(ApplyingSchool.SchoolStats.RallyStatus, ref TempRaRallySchoolStatistics);

                            AddOneApplicationSchoolStatistics(ApplyingSchool, ref TempRaRallySchoolStatistics);
                        }
                    } // for
                } // for
            }
        }

        public void CalculateAllEssayStatistics()
        {
            // Company all-up
            CalculateEssayStatistics(Global.SOF_Applications.Values.ToList<SOF_Application>(), Statistics.RallySchoolStatsList, Statistics.RallyOfRallySchoolStats);

            // Cities
            for (int i = 0; i < CityDB.NoOfCities; i++)
                CalculateEssayStatistics(CityDB.Cities[i].Students, CityDB.Cities[i].RallySchoolStatsList, CityDB.Cities[i].RallyOfRallySchoolStats);

            // Teachers
            foreach (var Teacher in TeacherDB.Teachers)
                CalculateEssayStatistics(Teacher.Students, Teacher.RallySchoolStatsList, Teacher.RallyOfRallySchoolStats);
        }
    }
}
